package org.xiaoxin.onecoupon.merchant.admin.job;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.xiaoxin.onecoupon.merchant.admin.common.enums.CouponTaskStatusEnum;
import org.xiaoxin.onecoupon.merchant.admin.dao.entity.CouponTaskDO;
import org.xiaoxin.onecoupon.merchant.admin.dao.mapper.CouponTaskMapper;
import org.xiaoxin.onecoupon.merchant.admin.mq.event.CouponTaskExecuteEvent;
import org.xiaoxin.onecoupon.merchant.admin.mq.producer.CouponTaskActualExecuteProducer;

import java.lang.management.LockInfo;
import java.util.Date;
import java.util.List;

/**
 * 优惠券推送任务扫描定时发送记录 XXL-Job 处理器
 * @author xiaoxin
 * 2025/4/21
 */
@Component
@RequiredArgsConstructor
public class CouponTaskJobHandler extends IJobHandler {
    private  final CouponTaskActualExecuteProducer couponTaskActualExecuteProducer;
    private  final  CouponTaskMapper couponTaskMapper;
    private static  final   int MAX_LIMIT=100;
    //execute() 这是 XXL-Job 调度任务的入口方法。当定时任务触发时，XXL-Job 框架会调用此方法。
    @XxlJob(value = "couponTemplateTask")
    public void execute() throws Exception {
        long initId=0;
        Date date = new Date();
        while (true){
            //获取已到执行时间待执行的优惠劵定时分发任务
            List<CouponTaskDO> couponTaskDOList=fetchPengdingTasks(initId,date);
            if (CollUtil.isEmpty(couponTaskDOList)){
                break;
            }
            //调用分发服务对用户发送优惠券
            for (CouponTaskDO couponTaskDO : couponTaskDOList) {
                distributeCoupon(couponTaskDO);
            }
            //查询出来的数据如果小于 MAX_LIMIT 意味着后面将不再有数据，返回即可
            if (couponTaskDOList.size()<MAX_LIMIT){
                break;
            }
            //当查询到的待处理任务数量等于MAX_LIMIT时，循环会继续，此时更新initId是为了在下一次迭代中查询下一批任务
            //更新 initId 为当前列表中最大 ID
            initId=couponTaskDOList.stream().mapToLong(CouponTaskDO::getId).max().orElse(initId);
        }

    }

    private void distributeCoupon(CouponTaskDO couponTask) {
        // 修改延时执行推送任务任务状态为执行中
        CouponTaskDO couponTaskDO = CouponTaskDO.builder()
                .id(couponTask.getId())
                .status(CouponTaskStatusEnum.IN_PROGRESS.getStatus())
                .build();
        couponTaskMapper.updateById(couponTaskDO);
        //通过消息队列发送消息，由分发服务消费者消费该消息
        CouponTaskExecuteEvent couponTaskExecuteEvent = CouponTaskExecuteEvent.builder()
                .couponTaskId(couponTask.getId())
                .build();
        couponTaskActualExecuteProducer.sendMessage(couponTaskExecuteEvent);

    }

    private List<CouponTaskDO> fetchPengdingTasks(long initId, Date date) {
        LambdaQueryWrapper<CouponTaskDO> wrapper = Wrappers.lambdaQuery(CouponTaskDO.class)
                .eq(CouponTaskDO::getStatus, CouponTaskStatusEnum.PENDING.getStatus())
                .le(CouponTaskDO::getSendTime, date)
                .gt(CouponTaskDO::getId, initId)
                .last("LIMIT " + MAX_LIMIT);
        return  couponTaskMapper.selectList(wrapper);
    }
}
